package com.example.crm.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.example.crm.entity.Right;
import com.example.crm.service.IRightService;
import com.example.crm.service.IRoleService;

import javax.annotation.Resource;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Resource
    IRightService rightService;

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
//    @Value("${spring.data.redis.password}")
//    private String password;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Resource
    private IRoleService roleService;

    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    /**
     * 开启Shiro注解
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启aop注解
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor=new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    public RedisManager redisManager() {
        RedisManager ramManager = new RedisManager();
        ramManager.setHost(host);
        ramManager.setPort(port);
        // 如果需要密码，取消注释下一行
        // ramManager.setPassword(password);
        ramManager.setTimeout(timeout);
        // 注意这里，返回 ramManager 对象，而不是再次调用 redisManager() 方法
        return ramManager;
    }


    public RedisCacheManager cacheManager(){
        RedisCacheManager cacheManager=new RedisCacheManager();
        cacheManager.setRedisManager(redisManager());
        //缓存名称
        cacheManager.setPrincipalIdFieldName("usrName");
        //缓存有效时间
        cacheManager.setExpire(1800);
        return cacheManager;
    }

    //会话操作
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO sessionDao = new RedisSessionDAO();
        sessionDao.setRedisManager(redisManager());
        return sessionDao;
    }
    //会话管理
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm shiroRealm=new MyShiroRealm();
        //设置启用缓存，并设置缓存名称
        shiroRealm.setCachingEnabled(true);
        shiroRealm.setAuthorizationCachingEnabled(true);
        shiroRealm.setAuthenticationCacheName("authorizationCache");
        return shiroRealm;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        securityManager.setCacheManager(cacheManager());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }
    @Bean
   public ShiroFilterFactoryBean filterFactoryFactory(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactory = new ShiroFilterFactoryBean();
        shiroFilterFactory.setSecurityManager(securityManager);
        shiroFilterFactory.setLoginUrl("/tologin");
        shiroFilterFactory.setSuccessUrl("/main");
        shiroFilterFactory.setUnauthorizedUrl("/403");
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/fonts/**","anon");
        filterChainDefinitionMap.put("/images/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("localcss/**","anon");
        filterChainDefinitionMap.put("/localjs/**","anon");
        filterChainDefinitionMap.put("/dologin","anon");
        filterChainDefinitionMap.put("/logout","logout");
        List<Right> rights=rightService.list();
        for (Right right:rights){
            if(right.getRightUrl()!=null && !right.getRightUrl().trim().equals("")){
                filterChainDefinitionMap.put(right.getRightUrl(),"perms["+right.getRightCode()+"]");
            }
        }
        //配置认证访问:其他资源必须认证通过才能访问
        filterChainDefinitionMap.put("/**","authc");

        shiroFilterFactory.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactory;
   }
/*   @Bean(name = "shiroDialect")
   public ShiroDialect shiroDialect(){
        return new ShiroDialect();
   }*/
}
